home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cocktail / l2r.lha / l2r / lex.rex < prev    next >
OS/2 REXX Batch file  |  1992-08-20  |  16KB  |  584 lines

  1. /************************************************************************/
  2. /*                                    */
  3. /* specification of scanner for lex input language in rex syntax    */
  4. /*                                    */
  5. /************************************************************************/
  6.  
  7. EXPORT {
  8. # include <string.h>
  9. # include "Memory.h"
  10. # include "Positions.h"
  11. # include "StringMem.h"
  12. # include "StringBuf.h"
  13.  
  14. extern void print_startconds    ();
  15. extern void print_macrodefs    ();
  16. extern void print_local        ();
  17. extern void put_macro        ();
  18.  
  19. typedef struct    { tPosition Position;
  20.           char char_value;
  21.           char string_value [256];
  22.         } tScanAttribute;
  23.  
  24. extern void ErrorAttribute ();
  25. }
  26.  
  27. GLOBAL {
  28. # include <stdio.h>
  29. # include "Errors.h"
  30.  
  31. # define DPercent    1
  32. # define Startdef    4
  33. # define Translate    5
  34. # define Slash        6
  35. # define Dot        7
  36. # define Question    8
  37. # define Plus        9
  38. # define Times        10
  39. # define LParent    11
  40. # define RParent    12
  41. # define Bar        13
  42. # define Action        14
  43. # define Startcond    15
  44. # define Repeat        16
  45. # define Expansion    17
  46. # define Caret        18
  47. # define Pseudoaction    19
  48. # define String        20
  49. # define Charclass    21
  50. # define Char        22
  51. # define Macrodef    23
  52. # define Translation    24
  53. # define Newline    25
  54. # define Dollar        26
  55.  
  56. /* error codes */
  57. # define MissingBrace    9
  58. # define MissingQuote    10
  59. # define MissingDQuote    11
  60. # define UnclosedComment 12
  61. # define Error        3
  62.  
  63. static cardinal k, l;    /* temporary variables for string length    */
  64. static char v [256];    /* temporary variable for strings        */
  65. static int level;    /* counter for nested braces in actions        */
  66.  
  67. /* struct for lists of strings for start conditions and macro defs.    */
  68. typedef struct scell {
  69.         tStringRef car;
  70.         struct scell * cdr;
  71.            } cell;
  72.  
  73. static cell * startconds  = NULL;    /* list of start conditions    */
  74. static cell * definitions = NULL;    /* list of macro definitions    */
  75. static cell * local_section = NULL;    /* text of local section    */
  76.  
  77. /* constructor for string lists                        */
  78. static cell * cons (s, p)
  79.    tStringRef s;
  80.    cell * p;
  81. {
  82.   cell * q = (cell *) Alloc (sizeof (cell));
  83.   q->car = s;
  84.   q->cdr = p;
  85.   return q;
  86. }
  87.  
  88. /* procedures for printing the start conditions                */
  89. void aux_print_startconds (p)
  90.    cell * p;
  91. {
  92.   if (p != NULL) {
  93.     aux_print_startconds ((cell *) p->cdr);
  94.     (void) printf ("\t");
  95.     WriteString (stdout, p->car);
  96.     (void) printf (",\n");
  97.   }
  98. }
  99.  
  100. void print_startconds ()
  101. {
  102.   if (startconds != NULL) {
  103.     (void) printf ("\nSTART\n");
  104.     aux_print_startconds ((cell *) startconds->cdr);
  105.     (void) printf ("\t");
  106.     WriteString (stdout, startconds->car);
  107.     (void) printf ("\n");
  108.   }
  109. }
  110.  
  111. /* procedures for printing the macro definitions            */
  112. void aux_print_macrodefs (p)
  113.    cell * p;
  114. {
  115.   if (p != NULL) {
  116.     aux_print_macrodefs ((cell *) p->cdr);
  117.     (void) printf ("\t");
  118.     WriteString (stdout, p->car);
  119.     (void) printf ("\n");
  120.   }
  121. }
  122.  
  123. void print_macrodefs ()
  124. {
  125.   if (definitions != NULL) {
  126.     (void) printf ("\nDEFINE\n");
  127.     aux_print_macrodefs (definitions);
  128.   }
  129. }
  130.  
  131. /* procedures for printing the LOCAL section                */
  132. void aux_print_local (p)
  133.    cell * p;
  134. {
  135.   if (p != NULL) {
  136.     aux_print_local ((cell *) p->cdr);
  137.     WriteString (stdout, p->car);
  138.   }
  139. }
  140.  
  141. void print_local ()
  142. {
  143.   if (local_section != NULL) {
  144.     (void) printf ("LOCAL {\n");
  145.     aux_print_local (local_section);
  146.     (void) printf ("}\n");
  147.   }
  148. }
  149.  
  150. /* mut macro to list of definitions                    */
  151. void put_macro (p)
  152.    char *p;
  153. {
  154.   definitions = cons (PutString (p, strlen (p)), definitions);
  155. }
  156.  
  157. /* put string to text of LOCAL section                    */
  158. void put_local (p)
  159.    char *p;
  160. {
  161.   local_section = cons (PutString (p, strlen (p)), local_section);
  162. }
  163.  
  164.  
  165. /* attribute for tokens inserted by parser                */
  166. void ErrorAttribute (Token, Attribute)
  167.   int Token;
  168.   tScanAttribute * Attribute;
  169.   {
  170.     Attribute->char_value = '\0';
  171.   };
  172.  
  173. /* convert character in character class from LEX to REX format        */
  174. /* returns the number of characters read                */
  175. static int debracket (t, q)
  176.    char **t;
  177.    char *q;
  178. {
  179.   int x;
  180.   int r;
  181.   char *p = *t;
  182.  
  183.   if (*p == '\\') {
  184.     *q++ = *p++;
  185.     if ((*p >= '0') && (*p <= '7')) {    /* octal escape to decimal */
  186.       x = 0;
  187.       while ((*p >= '0') && (*p <= '7'))
  188.     x = 8 * x + *p++ - '0';
  189.       r = 1 + strlen (sprintf (q ,"%d", x));
  190.     } else {                /* any other escape    */
  191.       *q = *p++;
  192.       r = 2;
  193.     }
  194.   } else {                /* REX special chars    */
  195.     if ((*p == '-') || (*p == '}') || (*p == ' ') || (*p == '\\')) {
  196.       *q++ = '\\';
  197.       *q = *p++;
  198.       r = 2;
  199.     } else {                /* normal character    */
  200.       *q = *p++;
  201.       r = 1;
  202.     }
  203.   }
  204.   *t = p;
  205.   return r;
  206. }
  207. }
  208.  
  209. LOCAL { char *p; }
  210.  
  211. BEGIN {
  212.   (void) printf ("EXPORT {\n");
  213.   (void) printf ("# define lex_interface\n");
  214.   (void) printf ("# include \"Positions.h\"\n");
  215.   (void) printf ("typedef struct { tPosition Position; } tScanAttribute;\n");
  216.   (void) printf ("extern void ErrorAttribute ();\n");
  217.   (void) printf ("}\n\n");
  218.   (void) printf ("GLOBAL {\n");
  219.   (void) printf ("# define ECHO (void) printf (\"%%s\", yytext)\n");
  220.   (void) printf ("# define yyless yyLess\n");
  221.   (void) printf ("# define yyDoBEGIN(state) { yyPreviousStart = yyStartState; yyStartState = (state) ? (state) : 1; }\n");
  222.   (void) printf ("char yytext [256];\n");
  223. }
  224.  
  225. EOF {
  226. switch (yyStartState) {
  227.   case InAction    : ;
  228.   case MultiLine: ErrorMessage (MissingBrace, Error, Attribute.Position); break;
  229.   case String1    : ErrorMessage (MissingQuote, Error, Attribute.Position); break;
  230.   case String2    : ErrorMessage (MissingDQuote, Error, Attribute.Position); break;
  231.   case Comment    : ErrorMessage (UnclosedComment, Error, Attribute.Position); break;
  232.   default    : break;
  233. }
  234. }
  235.  
  236. DEFINE
  237.     OctDigit    = {0-7}.
  238.     UpperCase    = {A-Z}.
  239.     LowerCase    = {a-z}.
  240.     Digit        = {0-9}.
  241.     AnyChar        = - { \ \t \n }.
  242.     Bracketed    = ( - { ] \\ } | \\ OctDigit + | \\ ANY ).
  243.     WhiteSpace    = ( \ | \t ) +.
  244.  
  245. START
  246.     Target1,    /* scanning target after WhiteSpace        */
  247.     InTarget,    /* scanning text between %{ %}            */
  248.     InMacro,    /* scanning expression of macro definition    */
  249.     RulePart,    /* scanning rule part                */
  250.     Local,        /* scanning local section            */
  251.     InAction,    /* scanning action in rule part            */
  252.     MultiLine,    /* scanning multi line action            */
  253.     String1,    /* action text between single quotes        */
  254.     String2,    /* action text between double quotes        */
  255.     Comment,    /* action text in comments            */
  256.     AfterAction,    /* single line action scanned, but not at eol    */
  257.     InBrackets,    /* scanning character class            */
  258.     NowCaret    /* Caret is following after start condition    */
  259.  
  260. RULES
  261.  
  262. /* matching rule for %%, switching between scanner states */
  263. < "%%" ANY * \n / {\ \t \n } :
  264.     { yyEol (0);
  265.       if (yyStartState == STD) { yyStart (Local); }
  266.       else yyStart (InTarget);
  267.       return DPercent;
  268.     }
  269.  
  270. < "%%" ANY * \n    :
  271.     { yyEol (0);
  272.       if (yyStartState == STD) { yyStart (RulePart); }
  273.       else yyStart (InTarget);
  274.       return DPercent;
  275.     }
  276.  
  277. /* matching rules for tokens in definition part             */
  278. /* matching rules for target code, escape special characters        */
  279. #STD#    < WhiteSpace ANY * : { yyEcho; yyStart (Target1); }
  280.  
  281. #STD#    < "%{" : { yyStart (InTarget); }
  282.  
  283. #Target1# ANY + : { yyEcho; }
  284.  
  285. #Target1# \n : { yyPrevious; yyEcho; yyEol (0); }
  286.  
  287. #InTarget# - { % \n } + :
  288.     { if (yyStartState == Local) { (void) GetWord (v); put_local (v); } else yyEcho; }
  289.  
  290. #InTarget# % :
  291.     { if (yyStartState == Local) put_local ("%"); else yyEcho; }
  292.  
  293. #InTarget# \n :
  294.     { if (yyStartState == Local) put_local ("\n"); else yyEcho; yyEol (0); }
  295.  
  296. #InTarget# < "%}" ANY * : { yyStart (STD); }
  297.  
  298. #Local# ANY + :
  299.     { if (yyStartState == Local) { (void) GetWord (v); put_local (v); } else yyEcho; }
  300.  
  301. #Local# \n / { \ \t \n } :
  302.     { put_local ("\n"); yyEol (0); }
  303.  
  304. #Local# \n :
  305.     { put_local ("\n"); yyEol (0); yyStart (RulePart); }
  306.  
  307. /* process BEGIN macro */
  308. #InTarget, Target1, Local# BEGIN WhiteSpace -{;}* / ; :
  309.     { k = 5 + GetWord (& v [5]);
  310.       (void) strcpy (v, "yyDoBEGIN ");
  311.       v [10] = '(';
  312.       v [k++] = ')';
  313.       v [k] = '\0';
  314.       l += k;
  315.       if (yyStartState == Local) put_local (v);
  316.       else (void) printf ("%s", v);
  317.     }
  318.  
  319. /* matching rule for macro definition                    */
  320. #STD#    < ( UpperCase | LowerCase ) - { \ \t \n } * WhiteSpace ? :
  321.     { l = GetWord (Attribute.string_value);
  322.       while (Attribute.string_value [--l] <= ' ')
  323.         Attribute.string_value [l] = '\0';
  324.       Attribute.string_value [++l] = '_';
  325.       Attribute.string_value [++l] = '\0';
  326.       yyStart (InMacro);
  327.       return Macrodef;
  328.     }
  329.  
  330. /* matching rules for start definition                    */
  331. #STD#    < ( "%s" | "%S" ) ANY * :
  332.     { l = GetWord (v);
  333.       (void) strtok (v, " \t\n");
  334.       do {
  335.         p = strtok ((char *) NULL, " \t\n");
  336.         if (p) startconds = cons (PutString (p, strlen (p)), startconds);
  337.       } while (p);
  338.       return Startdef;
  339.     }
  340.  
  341. /* matching rules for character set table                */
  342. #STD#    < ( "%t" | "%T" ) : { return Translate; }
  343.  
  344. #STD#    Digit + WhiteSpace ANY * : { return Translation; }
  345.  
  346. /* lines containing LEX directives are skipped                */
  347. #STD#    < "%" - { sStT%\{\n } ANY * \n : { }
  348.  
  349. /* rule part */
  350. #RulePart# WhiteSpace \n : { yyEol (0); }
  351.  
  352. /* matching rules for operators in rule part */
  353. #InMacro, RulePart# "/" : { return Slash    ; }
  354. #InMacro, RulePart# "." : { return Dot        ; }
  355. #InMacro, RulePart# "?" : { return Question    ; }
  356. #InMacro, RulePart# "+" : { return Plus        ; }
  357. #InMacro, RulePart# "*" : { return Times    ; }
  358. #InMacro, RulePart# "(" : { return LParent    ; }
  359. #InMacro, RulePart# ")" : { return RParent    ; }
  360. #InMacro, RulePart# "|" : { return Bar        ; }
  361.  
  362. /* matching pseudo action */
  363. #RulePart# WhiteSpace "|" ANY * : { return Pseudoaction; }
  364.  
  365. /* matching rules for actions in rule part */
  366. #RulePart# WhiteSpace / - { { \n } : { yyStart (InAction); l = 0; }
  367.  
  368. /* process BEGIN macro */
  369. #InAction, MultiLine# BEGIN WhiteSpace -{;}* / ; :
  370.     { k = 5 + GetWord (& v [5]);
  371.       (void) strcpy (v, "yyDoBEGIN ");
  372.       v [10] = '(';
  373.       v [k++] = ')';
  374.       v [k] = '\0';
  375.       (void) strcpy (& Attribute.string_value [l], v);
  376.       l += k;
  377.     }
  378.  
  379. /* skip strings and comments, escape characters if necessary */
  380. #InAction, MultiLine# ' :
  381.     { yyStart (String1); Attribute.string_value [l++] = '\''; }
  382.  
  383. #String1# - { ' \t \n } + :
  384.     { l += GetWord (& Attribute.string_value [l]); }
  385.  
  386. #String1# ' : { yyPrevious; Attribute.string_value [l++] = '\''; }
  387.  
  388. #InAction, MultiLine# \" :
  389.     { yyStart (String2); Attribute.string_value [l++] = '"'; }
  390.  
  391. #String2# - { " \t \n } + :
  392.     { l += GetWord (& Attribute.string_value [l]); }
  393.  
  394. #String2# \" : { yyPrevious; Attribute.string_value [l++] = '"'; }
  395.  
  396. #STD, InAction, MultiLine# "/*" :-
  397.     { yyStart (Comment); l += GetWord (& Attribute.string_value [l]); }
  398.  
  399. #Comment# - { * \t \n } + | "*" :-
  400.     { l += GetWord (& Attribute.string_value [l]); }
  401.  
  402. #Comment# "*/" :-
  403.     { yyPrevious; l += GetWord (& Attribute.string_value [l]); }
  404.  
  405. #String1, String2, Comment# \n :
  406.     { Attribute.string_value [l++] = '\n';
  407.       Attribute.string_value [l++] = '\0';
  408.       l = 0;
  409.       yyEol (0);
  410.       return Action;
  411.     }
  412.  
  413. #String1, String2, Comment# \t : { Attribute.string_value [l++] = '\t'; yyTab; }
  414.  
  415. #InAction# -{ ; \" ' } : { l += GetWord (& Attribute.string_value [l]); }
  416.  
  417. /* detect end of action */
  418. #InAction# ";" / \n :
  419.     { yyStart (RulePart);
  420.       Attribute.string_value [l++] = ';';
  421.       Attribute.string_value [l++] = '\0';
  422.       return Action;
  423.     }
  424.  
  425. #InAction# ";" :
  426.     { yyStart (AfterAction);
  427.       Attribute.string_value [l++] = ';';
  428.       Attribute.string_value [l++] = '\0';
  429.       return Action;
  430.     }
  431.  
  432. #AfterAction# ANY * : { yyStart (RulePart); }
  433.  
  434. /* actions in curly braces */
  435. #RulePart# WhiteSpace ? "{" : { yyStart (MultiLine); level = 1; l = 0; }
  436.  
  437. #MultiLine# "{" : { Attribute.string_value [l++] = '{'; ++ level; }
  438.  
  439. #MultiLine# "}" / \n :
  440.     { if (-- level == 0) { Attribute.string_value [l] = '\0'; yyStart (RulePart); return Action; }
  441.       else Attribute.string_value [l++] = '}';
  442.     }
  443.  
  444. #MultiLine# "}" :
  445.     { if (-- level == 0) { Attribute.string_value [l] = '\0'; yyStart (AfterAction); return Action; }
  446.       else Attribute.string_value [l++] = '}';
  447.     }
  448.  
  449. #MultiLine# \n :
  450.     { l += GetWord (& Attribute.string_value [l]); l = 0; yyEol (0); return Action; }
  451.  
  452. #MultiLine# - { { \} \n } :
  453.     { (void) GetWord (& Attribute.string_value [l++]); }
  454.  
  455. /* match start condition and prepare matching of caret */
  456. #RulePart# < "<" - { > \n } + ">" / "^" :
  457.     { yyStart (NowCaret);
  458.       l = GetWord (Attribute.string_value);
  459.       Attribute.string_value [0] = '#';
  460.       Attribute.string_value [l-1] = '#';
  461.       return Startcond;
  462.     }
  463.  
  464. /* match start condition */
  465. #RulePart# < "<" - { > \n } + ">" :
  466.     { l = GetWord (Attribute.string_value);
  467.       Attribute.string_value [0] = '#';
  468.       Attribute.string_value [l-1] = '#';
  469.       return Startcond;
  470.     }
  471.  
  472. /* match repeat with one or two counts */
  473. #InMacro, RulePart# "{" Digit + ( "," Digit + ) ? "}" :
  474.     { l = GetWord (Attribute.string_value);
  475.       Attribute.string_value [0] = '[';
  476.       Attribute.string_value [l-1] = ']';
  477.       p = & Attribute.string_value [1];
  478.       while ((*p >= '0') && (*p <= '9')) p++;
  479.       if (*p == ',') *p = '-';
  480.       return Repeat;
  481.     }
  482.  
  483. /* match name expansion */
  484. #InMacro, RulePart# "{" ( UpperCase | LowerCase ) - { \} \n } * "}" :
  485.     { l = GetWord (Attribute.string_value);
  486.       Attribute.string_value [0] = ' ';
  487.       Attribute.string_value [l-1] = '_';
  488.       Attribute.string_value [l++] = ' ';
  489.       Attribute.string_value [l] = '\0';
  490.       return Expansion;
  491.     }
  492.  
  493. /* match caret at beginning of line */
  494. #RulePart# < "^"    : { return Caret; }
  495.  
  496. /* match caret after start condition */
  497. #NowCaret# "^"    : { yyStart (RulePart); return Caret; }
  498.  
  499. /* match escape with octal representation */
  500. #InMacro, RulePart# "\" OctDigit + :
  501.     { Attribute.char_value = 0;
  502.       (void) GetWord (v);
  503.       p = & v [1];
  504.       while (*p) Attribute.char_value = 8 * Attribute.char_value + *p++ - '0';
  505.       return Char;
  506.     }
  507.  
  508. /* match character escape */
  509. #InMacro, RulePart# "\" ANY :
  510.     { (void) GetWord (v);
  511.       switch (v [1]) {
  512.         case 'n'    : Attribute.char_value = 10; break;
  513.         case 'b'    : Attribute.char_value = 8 ; break;
  514.         case 't'    : Attribute.char_value = 9 ; break;
  515.         case 'f'    : Attribute.char_value = 12; break;
  516.         case 'r'    : Attribute.char_value = 13; break;
  517.         default    : Attribute.char_value = v [1]; break;
  518.       }
  519.       return Char;
  520.     }
  521.  
  522. /* NOT has to be escaped */
  523. #InMacro, RulePart# \NOT :
  524.     { (void) strcpy (Attribute.string_value, "\\NOT"); return String; }
  525.  
  526. /* numbers have to be escaped */
  527. #InMacro, RulePart# Digit + :
  528.     { l = GetWord (& Attribute.string_value [1]);
  529.       Attribute.string_value [0] = '"';
  530.       Attribute.string_value [++l] = '"';
  531.       Attribute.string_value [++l] = '\0';
  532.       return String;
  533.     }
  534.  
  535. /* match string */
  536. #InMacro, RulePart# \" - {\n"} * \" :
  537.     { l = GetWord (Attribute.string_value); return String; }
  538.  
  539. /* match character class */
  540. /* at first, match opening bracket and caret, if existing */
  541. #InMacro, RulePart# "[" "^" ? :
  542.     { yyStart (InBrackets);
  543.       l = GetWord (Attribute.string_value);
  544.       if (l == 2) {
  545.         Attribute.string_value [0] = '-';
  546.         Attribute.string_value [1] = '{';
  547.       }
  548.       else
  549.         Attribute.string_value [0] = '{';
  550.     }
  551.  
  552. /* match character range char - char */
  553. #InBrackets# Bracketed "-" Bracketed :-
  554.     { (void) GetWord (v);
  555.       p = v;
  556.       l += debracket (& p, & Attribute.string_value [l]);
  557.       Attribute.string_value [l++] = '-';
  558.       p++;
  559.       l += debracket (& p, & Attribute.string_value [l]);
  560.     }
  561.  
  562. /* match arbitrary character */
  563. #InBrackets# Bracketed :-
  564.     { (void) GetWord (v);
  565.       p = v;
  566.       l += debracket (& p, & Attribute.string_value [l]);
  567.     }
  568.  
  569. /* match closing bracket */
  570. #InBrackets# "]" :-
  571.     { yyPrevious;
  572.       Attribute.string_value [l++] = '}';
  573.       Attribute.string_value [l++] = '\0';
  574.       return Charclass; }
  575.  
  576. /* match dollar as candidate for right context indicator */
  577. #InMacro, RulePart# "$" / { | \ \t } : { return Dollar; }
  578.  
  579. /* match letter or special character if not matched by previous rules */
  580. AnyChar : { (void) GetWord (v); Attribute.char_value = v [0]; return Char; }
  581.  
  582. /* match newline and stop accepting macro expansion */
  583. \n    : { yyEol (0); if (yyStartState == InMacro) yyStart (STD); return Newline; }
  584.